home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / msdos / editors / eedraw / src / ed / eemodify.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-26  |  43.6 KB  |  1,274 lines

  1. /*****************************************************************************
  2. *   Program to draw EE diagrams.                         *
  3. *                                         *
  4. * This module handles object modification.                     *
  5. *                                         *
  6. * Written by:  Gershon Elber            IBM PC Ver 1.0,    Oct. 1989    *
  7. *****************************************************************************/
  8.  
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <alloc.h>
  13. #include <dos.h>
  14. #include "Program.h"
  15. #include "EECreate.h"
  16. #include "EELibs.h"
  17. #include "EEModify.h"
  18. #include "EERedraw.h"
  19. #include "EEString.h"
  20. #include "EELayer.h"
  21. #include "Primary.h"    /* Primary Drawing Layers Designation Numbers */
  22.  
  23. #define UNDELETE_STACK_SIZE 10
  24.  
  25. static char *EditMenuStrs[] =
  26. {
  27.     "Done",
  28.     "",
  29.     "EditPartName",
  30.     "Un/DrawChipName",
  31.     "ReposPartName",
  32.     "ReposChipName",
  33.     "RePosLibItem"
  34. };
  35. #define EDIT_MENU_SIZE (sizeof(EditMenuStrs) / sizeof(char *))
  36.  
  37. static int
  38.     UnDeleteStackPtr = 0;
  39. static DrawGenericStruct
  40.     *LastSnappedStruct = NULL;
  41. static DrawGenericStruct *UnDeleteStack[UNDELETE_STACK_SIZE];
  42. static int PickedBoxMinX, PickedBoxMinY, PickedBoxMaxX, PickedBoxMaxY;
  43. static IntrCursorShapeStruct Cursor;
  44. static IntrPopUpMenuStruct
  45.     *EditPopUpMenu = NULL;
  46.  
  47. static void MoveStructs(DrawPickedStruct *DrawStructs, int Dx, int Dy);
  48. static void MoveOneStruct(DrawGenericStruct *DrawStructs, int Dx, int Dy);
  49. static int PlaceStruct(DrawGenericStruct *DrawStruct);
  50. static DrawGenericStruct *CopyStructLocal(DrawGenericStruct *DrawStruct);
  51.  
  52. /*****************************************************************************
  53. * Routine to move an object(s) to a new position.                 *
  54. * If DrawStruct is of type DrawPickedStruct, a list of objects picked is     *
  55. * assumed, otherwise exactly one structure is assumed been picked.         *
  56. *****************************************************************************/
  57. BooleanType MoveStruct(DrawGenericStruct *DrawStruct)
  58. {
  59.     BooleanType RetVal;
  60.  
  61.     /* Remove this structure(s) from display and global structure list.         */
  62.     DeleteStruct(DrawStruct);
  63.  
  64.     RetVal = PlaceStruct(DrawStruct);        /* Place it in its new position. */
  65.  
  66.     UnDeleteStruct();             /* And undelete it in its new position. */
  67.  
  68.     return RetVal;
  69. }
  70.  
  71. /*****************************************************************************
  72. * Routine to copy a new entity of an object and reposition it.             *
  73. * If DrawStruct is of type DrawPickedStruct, a list of objects picked is     *
  74. * assumed, otherwise exactly one structure is assumed been picked.         *
  75. *****************************************************************************/
  76. BooleanType CopyStruct(DrawGenericStruct *DrawStruct)
  77. {
  78.     BooleanType RetVal;
  79.  
  80.     DrawGenericStruct *NewDrawStruct;
  81.     DrawPickedStruct *PickedItem,
  82.         *PickedList = NULL;
  83.  
  84.     NewDrawStruct = CopyStructLocal(DrawStruct);
  85.  
  86.     if ((RetVal = PlaceStruct(NewDrawStruct)) != FALSE) {
  87.     /* Draw the new structure and chain it in: */
  88.     if (NewDrawStruct -> StructType == DRAW_PICK_ITEM_STRUCT_TYPE) {
  89.         RedrawStructList(NewDrawStruct, GR_COPY_PUT, EE_DRAW_COLOR);
  90.  
  91.         PickedList = (DrawPickedStruct *) NewDrawStruct;
  92.         while (PickedList) {
  93.         PickedList -> PickedStruct -> Pnext =
  94.                             EEActiveWindow -> EEDrawList;
  95.         EEActiveWindow -> EEDrawList = PickedList -> PickedStruct;
  96.  
  97.         PickedItem = PickedList;
  98.         PickedList = PickedList -> Pnext;
  99.         MyFree((VoidPtr) PickedItem);
  100.         }
  101.     }
  102.     else {
  103.         RedrawOneStruct(NewDrawStruct, GR_COPY_PUT, EE_DRAW_COLOR);
  104.  
  105.         NewDrawStruct->Pnext = EEActiveWindow -> EEDrawList;
  106.         EEActiveWindow -> EEDrawList = NewDrawStruct;
  107.     }
  108.     }
  109.     else
  110.     FreeStruct(NewDrawStruct);
  111.  
  112.     /* Free the original DrawPickedStruct chain: */
  113.     if (DrawStruct -> StructType == DRAW_PICK_ITEM_STRUCT_TYPE) {
  114.     PickedList = (DrawPickedStruct *) DrawStruct;
  115.  
  116.     while (PickedList != NULL) {
  117.         PickedItem = PickedList;
  118.         PickedList = PickedList -> Pnext;
  119.         MyFree((VoidPtr) PickedItem);
  120.     }
  121.     }
  122.  
  123.     return RetVal;
  124. }
  125.  
  126. /*****************************************************************************
  127. * Routine to delete an object from global drawing object list.             *
  128. *****************************************************************************/
  129. void DeleteStruct(DrawGenericStruct *DrawStruct)
  130. {
  131.     int i;
  132.     DrawGenericStruct
  133.     *DrawList = EEActiveWindow -> EEDrawList;
  134.     DrawPickedStruct
  135.     *PickedList = NULL;
  136.  
  137.     /* Effectively hides the cursor to prevent from its    interference with   */
  138.     /* the erased object(s).                            */
  139.     IntrPushCursorType();
  140.  
  141.     if (DrawStruct -> StructType == DRAW_PICK_ITEM_STRUCT_TYPE) {
  142.     PickedList = (DrawPickedStruct *) DrawStruct;
  143.     while (PickedList) {
  144.         if (PickedList -> PickedStruct == EEActiveWindow -> EEDrawList)
  145.         EEActiveWindow -> EEDrawList =
  146.                     EEActiveWindow -> EEDrawList -> Pnext;
  147.         else {
  148.         DrawList = EEActiveWindow -> EEDrawList;
  149.         while (DrawList -> Pnext) {
  150.             if (DrawList -> Pnext == PickedList -> PickedStruct) {
  151.             DrawList -> Pnext = DrawList -> Pnext -> Pnext;
  152.             break;
  153.             }
  154.             DrawList = DrawList -> Pnext;
  155.         }
  156.         }
  157.  
  158.         PickedList = PickedList -> Pnext;
  159.     }
  160.  
  161.     RedrawStructList(DrawStruct, GR_COPY_PUT, EE_ERASE_COLOR);
  162.     }
  163.     else {
  164.     if (DrawStruct == EEActiveWindow -> EEDrawList)
  165.         EEActiveWindow -> EEDrawList =
  166.                 EEActiveWindow -> EEDrawList -> Pnext;
  167.     else {
  168.         DrawList = EEActiveWindow -> EEDrawList;
  169.         while (DrawList -> Pnext) {
  170.         if (DrawList -> Pnext == DrawStruct) {
  171.             DrawList -> Pnext = DrawList -> Pnext -> Pnext;
  172.             break;
  173.         }
  174.         DrawList = DrawList -> Pnext;
  175.         }
  176.     }
  177.  
  178.     RedrawOneStruct(DrawStruct, GR_COPY_PUT, EE_ERASE_COLOR);
  179.     }
  180.  
  181.     if (UnDeleteStackPtr >= UNDELETE_STACK_SIZE - 1) {
  182.     /* Delete last deleted item, and shift stack. */
  183.     FreeStruct(UnDeleteStack[0]);
  184.     for (i = 0; i < UnDeleteStackPtr; i++)
  185.         UnDeleteStack[i] = UnDeleteStack[i + 1];
  186.     UnDeleteStack[UnDeleteStackPtr] = DrawStruct;
  187.     }
  188.     else
  189.     UnDeleteStack[UnDeleteStackPtr++] = DrawStruct;
  190.  
  191.     IntrPopCursorType();                /* Reenable the cursor. */
  192. }
  193.  
  194. /*****************************************************************************
  195. * Routine to cut an object from global drawing object list.             *
  196. *   This routine is the same as delete but the original list is NOT removed. *
  197. *****************************************************************************/
  198. void CutStruct(DrawGenericStruct *DrawStruct)
  199. {
  200.     int i;
  201.     DrawPickedStruct *PickedItem, *PickedList;
  202.     DrawGenericStruct *DrawStructCopy;
  203.  
  204.     /* Make a copy of the original picked item. */
  205.     DrawStructCopy = CopyStructLocal(DrawStruct);
  206.  
  207.     if (DrawStruct -> StructType == DRAW_PICK_ITEM_STRUCT_TYPE) {
  208.     /* Delete the picked wrapper if this is a picked list. */
  209.         for (PickedList = (DrawPickedStruct *) DrawStruct; PickedList != NULL; ) {
  210.         PickedItem = PickedList;
  211.         PickedList = PickedList -> Pnext;
  212.         MyFree((VoidPtr) PickedItem);
  213.     }
  214.     }
  215.  
  216.     /* And push it into the delete stack: */
  217.     if (UnDeleteStackPtr >= UNDELETE_STACK_SIZE - 1) {
  218.     /* Delete last deleted item, and shift stack. */
  219.     FreeStruct(UnDeleteStack[0]);
  220.     for (i = 0; i < UnDeleteStackPtr; i++)
  221.         UnDeleteStack[i] = UnDeleteStack[i + 1];
  222.     UnDeleteStack[UnDeleteStackPtr] = DrawStructCopy;
  223.     }
  224.     else
  225.     UnDeleteStack[UnDeleteStackPtr++] = DrawStructCopy;
  226. }
  227.  
  228. /*****************************************************************************
  229. * Routine to undelete a structure from the undelete stack.             *
  230. *****************************************************************************/
  231. BooleanType UnDeleteStruct(void)
  232. {
  233.     DrawGenericStruct *DrawStruct;
  234.     DrawPickedStruct  *PickedItem,
  235.     *PickedList = NULL;
  236.  
  237.     if (UnDeleteStackPtr == 0) {
  238.     Cursor.CursorType = INTR_CURSOR_ARROW;
  239.     IntrQueryContinue("No struct to undelete", EEPopUpFrameColor,
  240.                   EEPopUpBackColor, EEPopUpForeColor,
  241.                           EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
  242.                           INTR_WNDW_PLACE_CENTER);
  243.         return FALSE;
  244.     }
  245.     else {
  246.     DrawStruct = UnDeleteStack[--UnDeleteStackPtr];
  247.     if (DrawStruct -> StructType == DRAW_PICK_ITEM_STRUCT_TYPE) {
  248.         RedrawStructList(DrawStruct, GR_COPY_PUT, EE_DRAW_COLOR);
  249.  
  250.         for (PickedList = (DrawPickedStruct *) DrawStruct;
  251.          PickedList != NULL; ) {
  252.         PickedList -> PickedStruct -> Pnext =
  253.                     EEActiveWindow -> EEDrawList;
  254.         EEActiveWindow -> EEDrawList = PickedList -> PickedStruct;
  255.  
  256.         PickedItem = PickedList;
  257.         PickedList = PickedList -> Pnext;
  258.         MyFree((VoidPtr) PickedItem);
  259.         }
  260.     }
  261.     else {
  262.         RedrawOneStruct(DrawStruct, GR_COPY_PUT, EE_DRAW_COLOR);
  263.  
  264.         DrawStruct -> Pnext = EEActiveWindow -> EEDrawList;
  265.         EEActiveWindow -> EEDrawList = DrawStruct;
  266.     }
  267.         return TRUE;
  268.     }
  269. }
  270.  
  271. /*****************************************************************************
  272. * Routine to paste a structure from the undelete stack.                 *
  273. *   This routine is the same as undelete but original list is NOT removed.   *
  274. *****************************************************************************/
  275. BooleanType PasteStruct(void)
  276. {
  277.     DrawGenericStruct *DrawStruct;
  278.     DrawPickedStruct  *PickedItem,
  279.     *PickedList = NULL;
  280.  
  281.     if (UnDeleteStackPtr == 0) {
  282.     Cursor.CursorType = INTR_CURSOR_ARROW;
  283.     IntrQueryContinue("No struct to paste", EEPopUpFrameColor,
  284.                   EEPopUpBackColor, EEPopUpForeColor,
  285.                           EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
  286.                           INTR_WNDW_PLACE_CENTER);
  287.         return FALSE;
  288.     }
  289.     else {
  290.     DrawStruct = CopyStructLocal(UnDeleteStack[UnDeleteStackPtr - 1]);
  291.         if (DrawStruct -> StructType == DRAW_PICK_ITEM_STRUCT_TYPE)
  292.         MoveStructs((DrawPickedStruct *) DrawStruct, EESnapDistance,
  293.                                      EESnapDistance);
  294.         else
  295.         MoveOneStruct(DrawStruct, EESnapDistance, EESnapDistance);
  296.         PlaceStruct(DrawStruct);
  297.     if (DrawStruct -> StructType == DRAW_PICK_ITEM_STRUCT_TYPE) {
  298.         RedrawStructList(DrawStruct, GR_COPY_PUT, EE_DRAW_COLOR);
  299.  
  300.         for (PickedList = (DrawPickedStruct *) DrawStruct;
  301.          PickedList != NULL; ) {
  302.         PickedList -> PickedStruct -> Pnext =
  303.                     EEActiveWindow -> EEDrawList;
  304.         EEActiveWindow -> EEDrawList = PickedList -> PickedStruct;
  305.  
  306.         PickedItem = PickedList;
  307.         PickedList = PickedList -> Pnext;
  308.         MyFree((VoidPtr) PickedItem);
  309.         }
  310.     }
  311.     else {
  312.         RedrawOneStruct(DrawStruct, GR_COPY_PUT, EE_DRAW_COLOR);
  313.  
  314.         DrawStruct -> Pnext = EEActiveWindow -> EEDrawList;
  315.         EEActiveWindow -> EEDrawList = DrawStruct;
  316.     }
  317.         return TRUE;
  318.     }
  319. }
  320.  
  321. /*****************************************************************************
  322. * Routine to drop a structure from the undelete top of stack.             *
  323. *****************************************************************************/
  324. void DropStruct(void)
  325. {
  326.     if (UnDeleteStackPtr == 0) {
  327.     Cursor.CursorType = INTR_CURSOR_ARROW;
  328.     IntrQueryContinue("No struct to drop", EEPopUpFrameColor,
  329.                   EEPopUpBackColor, EEPopUpForeColor,
  330.                           EEPopUpXorColor, EEWindowsFrameWidth, &Cursor,
  331.                           INTR_WNDW_PLACE_CENTER);
  332.     }
  333.     else {
  334.     IntrDrawMessage("Dropping top of stack", EEPopUpForeColor,
  335.                                  EEPopUpBackColor);
  336.     FreeStruct(UnDeleteStack[--UnDeleteStackPtr]);
  337.         delay(200);
  338.     IntrEraseMessage();
  339.     }
  340. }
  341.  
  342. /*****************************************************************************
  343. * Routine to place a given object.                         *
  344. *****************************************************************************/
  345. static BooleanType PlaceStruct(DrawGenericStruct *DrawStruct)
  346. {
  347.     int x, y;
  348.     BooleanType
  349.         RetVal = FALSE;
  350.  
  351.     delay(250);            /* Make sure no events are waiting in the queue. */
  352.     IntrInputFlush();
  353.  
  354.     IntrSetIdleFunction(AutoPanActiveWindow);
  355.  
  356.     switch (DrawStruct -> StructType) {
  357.     case DRAW_POLYLINE_STRUCT_TYPE:
  358.         RetVal = PlacePolylineStruct((DrawPolylineStruct *) DrawStruct);
  359.             break;
  360.     case DRAW_CONNECTION_STRUCT_TYPE:
  361.         GRCurrentCursorX = GRMapX(((DrawConnectionStruct *) DrawStruct) -> PosX);
  362.         GRCurrentCursorY = GRMapY(((DrawConnectionStruct *) DrawStruct) -> PosY);
  363.         RetVal = PlaceConnectionStruct((DrawConnectionStruct *) DrawStruct);
  364.             break;
  365.     case DRAW_TEXT_STRUCT_TYPE:
  366.         GRCurrentCursorX = GRMapX(((DrawTextStruct *) DrawStruct) -> PosX);
  367.         GRCurrentCursorY = GRMapY(((DrawTextStruct *) DrawStruct) -> PosY);
  368.         RetVal = PlaceTextStruct((DrawTextStruct *) DrawStruct);
  369.             break;
  370.     case DRAW_LIB_ITEM_STRUCT_TYPE:
  371.         GRCurrentCursorX = GRMapX(((DrawLibItemStruct *) DrawStruct) -> PosX);
  372.         GRCurrentCursorY = GRMapY(((DrawLibItemStruct *) DrawStruct) -> PosY);
  373.         RetVal = PlaceLibItem((DrawLibItemStruct *) DrawStruct);
  374.             break;
  375.     case DRAW_PICK_ITEM_STRUCT_TYPE:
  376.         /* Place a box instead: */
  377.         IntrPushCursorType();
  378.             Cursor.CursorType = INTR_CURSOR_BOX;
  379.             GRCurrentCursorX = (GRMapX(PickedBoxMaxX) - GRMapX(PickedBoxMinX)) / 2;
  380.             GRCurrentCursorY = (GRMapY(PickedBoxMaxY) - GRMapY(PickedBoxMinY)) / 2;
  381.             Cursor.Width = (GRMapX(PickedBoxMaxX) - GRMapX(PickedBoxMinX)) / 2;
  382.             Cursor.Height = (GRMapY(PickedBoxMaxY) - GRMapY(PickedBoxMinY)) / 2;
  383.         IntrSetCursorType(&Cursor);
  384.  
  385.         GRCurrentCursorX = GRMapX((PickedBoxMinX + PickedBoxMaxX) / 2);
  386.         GRCurrentCursorY = GRMapY((PickedBoxMinY + PickedBoxMaxY) / 2);
  387.  
  388.         IntrDrawMessage("Place picked box", EEPopUpForeColor,
  389.                                 EEPopUpBackColor);
  390.         /* Move all object is the selected block out of drawing area: */
  391.         MoveStructs((DrawPickedStruct *) DrawStruct, -10000, -10000);
  392.  
  393.         if (IntrGetEventWaitSA(&x, &y) == INTR_EVNT_SELECT) {
  394.         x = EE_SNAP(GRInvMapX(x));
  395.         y = EE_SNAP(GRInvMapY(y));
  396.  
  397.         MoveStructs((DrawPickedStruct *) DrawStruct,
  398.                 x - (PickedBoxMaxX + PickedBoxMinX) / 2 + 10000,
  399.                 y - (PickedBoxMaxY + PickedBoxMinY) / 2 + 10000);
  400.  
  401.         IntrPopCursorType();
  402.         IntrEraseMessage();
  403.         RetVal = TRUE;
  404.         }
  405.         else {
  406.         MoveStructs((DrawPickedStruct *) DrawStruct, 10000, 10000);
  407.  
  408.         IntrPopCursorType();
  409.         IntrEraseMessage();
  410.         RetVal = FALSE;
  411.         }
  412.             break;
  413.     }
  414.  
  415.     IntrSetIdleFunction(NULL);
  416.  
  417.     return RetVal;
  418. }
  419.  
  420. /*****************************************************************************
  421. * Given list of structures as DrawPickStruct list move them all by Dx, Dy    *
  422. * (given in drawing space).                             *
  423. *****************************************************************************/
  424. static void MoveStructs(DrawPickedStruct *DrawStructs, int Dx, int Dy)
  425. {
  426.     /* Make sure we will stay on the snap boundaries. */
  427.     Dx = EE_SNAP(Dx);
  428.     Dy = EE_SNAP(Dy);
  429.  
  430.     while (DrawStructs) {
  431.     MoveOneStruct(DrawStructs -> PickedStruct, Dx, Dy);
  432.  
  433.     DrawStructs = DrawStructs -> Pnext;
  434.     }
  435. }
  436.  
  437. /*****************************************************************************
  438. * Given a structures move it by Dx, Dy.                         *
  439. *****************************************************************************/
  440. static void MoveOneStruct(DrawGenericStruct *DrawStruct, int Dx, int Dy)
  441. {
  442.     int i, *Points;
  443.     DrawPolylineStruct *DrawPoly;
  444.     DrawConnectionStruct *DrawConnect;
  445.     DrawTextStruct *DrawText;
  446.     DrawLibItemStruct *DrawLibItem;
  447.  
  448.     switch (DrawStruct -> StructType) {
  449.         case DRAW_POLYLINE_STRUCT_TYPE:
  450.         DrawPoly = (DrawPolylineStruct *) DrawStruct;
  451.         Points = DrawPoly -> Points;
  452.         for (i = 0; i < DrawPoly -> NumOfPoints; i++) {
  453.             Points[i * 2] += Dx;
  454.             Points[i * 2 + 1] += Dy;
  455.         }
  456.         break;
  457.     case DRAW_CONNECTION_STRUCT_TYPE:
  458.         DrawConnect = (DrawConnectionStruct *) DrawStruct;
  459.         DrawConnect -> PosX += Dx;
  460.         DrawConnect -> PosY += Dy;
  461.         break;
  462.     case DRAW_TEXT_STRUCT_TYPE:
  463.         DrawText = (DrawTextStruct *) DrawStruct;
  464.         DrawText -> PosX += Dx;
  465.         DrawText -> PosY += Dy;
  466.         break;
  467.     case DRAW_LIB_ITEM_STRUCT_TYPE:
  468.         DrawLibItem = (DrawLibItemStruct *) DrawStruct;
  469.         DrawLibItem -> PosX += Dx;
  470.         DrawLibItem -> PosY += Dy;
  471.         DrawLibItem -> PartNameX += Dx;
  472.         DrawLibItem -> PartNameY += Dy;
  473.         DrawLibItem -> ChipNameX += Dx;
  474.         DrawLibItem -> ChipNameY += Dy;
  475.         DrawLibItem -> BBoxMinX += Dx;
  476.         DrawLibItem -> BBoxMinY += Dy;
  477.         DrawLibItem -> BBoxMaxX += Dx;
  478.         DrawLibItem -> BBoxMaxY += Dy;
  479.         break;
  480.     }
  481. }
  482.  
  483. /*****************************************************************************
  484. * Routine to edit library items and modify its entries.                 *
  485. *****************************************************************************/
  486. BooleanType EditLibraryItem(void)
  487. {
  488.     int PopPosition;
  489.     char Line[LINE_LEN_SHORT], *OldStr;
  490.     TextOrientationType Orient;
  491.     BooleanType
  492.         RetVal = FALSE;
  493.     DrawLibItemStruct *LibItem;
  494.     DrawPickedStruct *PickedItem,
  495.     *PickedList = NULL;
  496.  
  497.     Cursor.CursorType = INTR_CURSOR_ARROW;
  498.     if (EditPopUpMenu == NULL) {
  499.         EditPopUpMenu =
  500.             IntrPopUpMenuCreate("Modify Lib Item", (char **) EditMenuStrs,
  501.                         0, EDIT_MENU_SIZE, EEPopUpFrameColor,
  502.                               EEPopUpBackColor, EEPopUpForeColor,
  503.                             EEPopUpXorColor, EEWindowsFrameWidth, &Cursor);
  504.     }
  505.  
  506.     LibItem = (DrawLibItemStruct *) PickStruct("Pick Library Item to Edit:",
  507.                                         TRUE);
  508.  
  509.     PopPosition = GRMapX(LibItem -> PosX) < GRScreenMaxX / 2 ?
  510.                             INTR_WNDW_PLACE_RIGHT :
  511.                             INTR_WNDW_PLACE_LEFT;
  512.  
  513.     if (LibItem != NULL &&
  514.     LibItem -> StructType == DRAW_LIB_ITEM_STRUCT_TYPE) {
  515.     DrawLibPart(LibItem, GR_COPY_PUT, EE_HIGHLIGHT_COLOR);
  516.     SetHighLightStruct((DrawGenericStruct *) LibItem);
  517.  
  518.     while (IntrPopUpMenu(EditPopUpMenu, PopPosition) &&
  519.            EditPopUpMenu -> SelectedIndex != 0) {
  520.         switch (EditPopUpMenu -> SelectedIndex) {
  521.             case 2: /* EditPartName */
  522.                 if (LibItem -> PartName != NULL) {
  523.                     strcpy(Line, LibItem -> PartName);
  524.                     OldStr = LibItem -> PartName;
  525.                     LibItem -> PartName = NULL;
  526.                 }
  527.                 else {
  528.                     Line[0] = 0;
  529.                     OldStr = NULL;
  530.                 }
  531.  
  532.                 IntrQueryLine("Enter new part name:", Line,
  533.                 LINE_LEN_SHORT - 1, EEPopUpFrameColor, EEPopUpBackColor,
  534.                 EEPopUpForeColor, EEWindowsFrameWidth, PopPosition);
  535.  
  536.                 if (OldStr != NULL) {
  537.                     GRSetWriteMode(GR_COPY_PUT);
  538.                     GRSetColor(EE_ERASE_COLOR);
  539.                     PutTextInfo(LibItem -> PartNameOrient,
  540.                             LibItem -> PartNameX,
  541.                             LibItem -> PartNameY,
  542.                     1,
  543.                     OldStr);
  544.                     MyFree((VoidPtr) OldStr);
  545.                 }
  546.  
  547.                 if (strlen(Line) > 0) {
  548.                     LibItem -> PartName = strdup(Line);
  549.                     if (OldStr == NULL) {
  550.                         LibItem -> PartNameX = LibItem -> PosX;
  551.                         LibItem -> PartNameY = LibItem -> PosY;
  552.                     }
  553.                     if (LibItem -> PartNameOrient == TEXT_ORIENT_NON)
  554.                         PlaceString(LibItem -> PartName,
  555.                     &LibItem -> PartNameOrient,
  556.                     1,
  557.                             &LibItem -> PartNameX,
  558.                     &LibItem -> PartNameY,
  559.                                     PopPosition);
  560.                     GRSetWriteMode(GR_COPY_PUT);
  561.                     GRSetColor(ReturnLayerColor(LAYER_REFDES));
  562.                     PutTextInfo(LibItem -> PartNameOrient,
  563.                     LibItem -> PartNameX,
  564.                     LibItem -> PartNameY,
  565.                     1,
  566.                     LibItem -> PartName);
  567.                 }
  568.                 else
  569.                 LibItem -> PartNameOrient = TEXT_ORIENT_NON;
  570.                 RetVal = TRUE;
  571.                 break;
  572.             case 3: /* Un/DrawChipName */
  573.             if (CanDrawChipName(LibItem -> ChipName)) {
  574.             if (LibItem -> ChipNameOrient != TEXT_ORIENT_NON) {
  575.                 GRSetWriteMode(GR_COPY_PUT);
  576.                 GRSetColor(EE_ERASE_COLOR);
  577.                 PutTextInfo(LibItem -> ChipNameOrient,
  578.                             LibItem -> ChipNameX,
  579.                             LibItem -> ChipNameY,
  580.                     1,
  581.                     LibItem -> ChipName);
  582.                 LibItem -> ChipNameOrient = TEXT_ORIENT_NON;
  583.             }
  584.                 else {
  585.                 LibItem -> ChipNameX = LibItem -> PosX;
  586.                         LibItem -> ChipNameY = LibItem -> PosY;
  587.                 if (PlaceString(LibItem -> ChipName,
  588.                             &LibItem -> ChipNameOrient,
  589.                         1,
  590.                         &LibItem -> ChipNameX,
  591.                         &LibItem -> ChipNameY,
  592.                                     PopPosition)) {
  593.                 GRSetWriteMode(GR_COPY_PUT);
  594.                 GRSetColor(ReturnLayerColor(LAYER_DEVICE));
  595.                 PutTextInfo(LibItem -> ChipNameOrient,
  596.                         LibItem -> ChipNameX,
  597.                         LibItem -> ChipNameY,
  598.                         1,
  599.                         LibItem -> ChipName);
  600.                 }
  601.             }
  602.             RetVal = TRUE;
  603.                 }
  604.                 else
  605.                     IntrQueryContinue("Chip name is NOT drawable for this item",
  606.                               EEPopUpFrameColor, EEPopUpBackColor,
  607.                               EEPopUpForeColor, EEPopUpXorColor,
  608.                       EEWindowsFrameWidth, &Cursor,
  609.                            PopPosition);
  610.                 break;
  611.             case 4: /* ReposPartName */
  612.                 if (LibItem -> PartNameOrient == TEXT_ORIENT_NON) {
  613.                 Cursor.CursorType = INTR_CURSOR_ARROW;
  614.                     IntrQueryContinue("Picked item has no part name",
  615.                               EEPopUpFrameColor, EEPopUpBackColor,
  616.                               EEPopUpForeColor, EEPopUpXorColor,
  617.                       EEWindowsFrameWidth, &Cursor,
  618.                            PopPosition);
  619.                     break;
  620.                 }
  621.  
  622.                 GRSetWriteMode(GR_COPY_PUT);
  623.                 GRSetColor(EE_ERASE_COLOR);
  624.                 PutTextInfo(LibItem -> PartNameOrient,
  625.                 LibItem -> PartNameX,
  626.                 LibItem -> PartNameY,
  627.                 1,
  628.                 LibItem -> PartName);
  629.  
  630.             /* Since when auto panning it will be redrawn, we        */
  631.             /* disable this string drawing temporarily.             */
  632.             Orient = LibItem -> PartNameOrient;
  633.             LibItem -> PartNameOrient = TEXT_ORIENT_NON;
  634.                 RetVal = PlaceString(LibItem -> PartName,
  635.                      &Orient,
  636.                      1,
  637.                      &LibItem -> PartNameX,
  638.                      &LibItem -> PartNameY,
  639.                                  PopPosition);
  640.             LibItem -> PartNameOrient = Orient;
  641.  
  642.                 GRSetWriteMode(GR_COPY_PUT);
  643.             GRSetColor(ReturnLayerColor(LAYER_REFDES));
  644.             PutTextInfo(LibItem -> PartNameOrient,
  645.                 LibItem -> PartNameX,
  646.                 LibItem -> PartNameY,
  647.                 1,
  648.                 LibItem -> PartName);
  649.                 break;
  650.             case 5: /* ReposChipName */
  651.                 if (LibItem -> ChipNameOrient == TEXT_ORIENT_NON ||
  652.             !CanDrawChipName(LibItem -> ChipName)) {
  653.                     Cursor.CursorType = INTR_CURSOR_ARROW;
  654.                     IntrQueryContinue("Picked item has no chip name",
  655.                       EEPopUpFrameColor, EEPopUpBackColor,
  656.                                       EEPopUpForeColor, EEPopUpXorColor,
  657.                                       EEWindowsFrameWidth, &Cursor,
  658.                                       PopPosition);
  659.                     break;
  660.                 }
  661.  
  662.             GRSetWriteMode(GR_COPY_PUT);
  663.             GRSetColor(EE_ERASE_COLOR);
  664.             PutTextInfo(LibItem -> ChipNameOrient,
  665.                 LibItem -> ChipNameX,
  666.                 LibItem -> ChipNameY,
  667.                 1,
  668.                 LibItem -> ChipName);
  669.  
  670.             /* Since when auto panning it will be redrawn, we        */
  671.             /* disable this string drawing temporarily.             */
  672.             Orient = LibItem -> ChipNameOrient;
  673.             LibItem -> ChipNameOrient = TEXT_ORIENT_NON;
  674.             RetVal = PlaceString(LibItem -> ChipName,
  675.                      &Orient,
  676.                      1,
  677.                      &LibItem -> ChipNameX,
  678.                      &LibItem -> ChipNameY,
  679.                                  PopPosition);
  680.             LibItem -> ChipNameOrient = Orient;
  681.  
  682.                 GRSetWriteMode(GR_COPY_PUT);
  683.             GRSetColor(ReturnLayerColor(LAYER_DEVICE));
  684.             PutTextInfo(LibItem -> ChipNameOrient,
  685.                     LibItem -> ChipNameX,
  686.                 LibItem -> ChipNameY,
  687.                 1,
  688.                 LibItem -> ChipName);
  689.                 break;
  690.             case 6: /* RePosLibItem */
  691.             RetVal = RePosLibItem(LibItem, PopPosition);
  692.                 break;
  693.         }
  694.     }
  695.  
  696.     SetHighLightStruct(NULL);
  697.     DrawLibPart(LibItem, GR_COPY_PUT, EE_DRAW_COLOR);
  698.     }
  699.  
  700.     if (LibItem -> StructType == DRAW_PICK_ITEM_STRUCT_TYPE) {
  701.     PickedList = (DrawPickedStruct *) LibItem;
  702.  
  703.     while (PickedList != NULL) {
  704.         /* More than one item were picked - free them all: */
  705.         PickedItem = PickedList;
  706.         PickedList = PickedList -> Pnext;
  707.         MyFree((VoidPtr) PickedItem);
  708.     }
  709.     }
  710.  
  711.     return RetVal;
  712. }
  713.  
  714. /*****************************************************************************
  715. * Routine to place a string. Returns string xy position and orientation      *
  716. * (vertically/horizontally). Returns TRUE if successful, FALSE otherwise.    *
  717. *****************************************************************************/
  718. BooleanType PlaceString(char *Str, TextOrientationType *Orient, int Scale,
  719.                           int *x, int *y, int PopPosition)
  720. {
  721.     int CrsrBoxWidth, CrsrBoxHeight,
  722.     LocalX = *x,
  723.         LocalY = *y,
  724.     Size = MAX(1, GRFontSize + (Scale - 1)) - DEFAULT_ZOOM_FACTOR;
  725.     TextOrientationType LocalOrient;
  726.     BooleanType RetVal;
  727.     char Line[LINE_LEN];
  728.  
  729.     Cursor.CursorType = INTR_CURSOR_ARROW;
  730.     GRPushTextSetting();
  731.     GRSetTextStyle(GRFontName, TEXT_ORIENT_HORIZ, Size);
  732.     if (IntrQueryYesNo("Horizonal?", EEPopUpFrameColor,
  733.                        EEPopUpBackColor, EEPopUpForeColor, EEPopUpXorColor,
  734.                        EEWindowsFrameWidth, &Cursor, PopPosition)) {
  735.     LocalOrient = TEXT_ORIENT_HORIZ;
  736.     CrsrBoxWidth = GRGetTextWidth(Str) / 2;
  737.     CrsrBoxHeight = GRGetTextHeight(Str) / 2;
  738.     }
  739.     else {
  740.     LocalOrient = TEXT_ORIENT_VERT;
  741.     CrsrBoxWidth = GRGetTextHeight(Str) / 2;
  742.     CrsrBoxHeight = GRGetTextWidth(Str) / 2;
  743.     }
  744.     GRPopTextSetting();
  745.  
  746.     IntrPushCursorType();
  747.     Cursor.CursorType = INTR_CURSOR_BOX;
  748.     Cursor.Width = CrsrBoxWidth;
  749.     Cursor.Height = CrsrBoxHeight;
  750.     IntrSetCursorType(&Cursor);
  751.  
  752.     sprintf(Line, "Place \"%s\":", Str);
  753.     IntrDrawMessage(Line, EEPopUpForeColor, EEPopUpBackColor);
  754.  
  755.     if (LocalX >= 0 && LocalY >= 0) {
  756.     GRCurrentCursorX = GRMapX(LocalX);
  757.     GRCurrentCursorY = GRMapY(LocalY);
  758.     }
  759.     PutCursorInActiveWindow();
  760.  
  761.     IntrSetIdleFunction(AutoPanActiveWindow);
  762.  
  763.     if ((RetVal = IntrGetEventWaitSA(&LocalX, &LocalY) == INTR_EVNT_SELECT)
  764.                                 != FALSE) {
  765.     *x = EE_SNAP(GRInvMapX(LocalX));
  766.     *y = EE_SNAP(GRInvMapY(LocalY));
  767.         *Orient = LocalOrient;
  768.     }
  769.  
  770.     IntrSetIdleFunction(NULL);
  771.  
  772.     Cursor.CursorType = INTR_CURSOR_ARROW;
  773.  
  774.     IntrPopCursorType();
  775.     IntrEraseMessage();
  776.  
  777.     return RetVal;
  778. }
  779.  
  780. /*****************************************************************************
  781. * Routine to create a new copy of given struct.                     *
  782. *****************************************************************************/
  783. static DrawGenericStruct *CopyStructLocal(DrawGenericStruct *DrawStruct)
  784. {
  785.     DrawGenericStruct
  786.         *NewDrawStruct = NULL;
  787.     DrawPickedStruct *NewPickedItem,
  788.     *PickedList = NULL,
  789.     *LastPickedItem = NULL;
  790.  
  791.     switch (DrawStruct -> StructType) {
  792.     case DRAW_POLYLINE_STRUCT_TYPE:
  793.         NewDrawStruct = (DrawGenericStruct *)
  794.                      MyMalloc(sizeof(DrawPolylineStruct));
  795.         GEN_COPY(NewDrawStruct, DrawStruct, sizeof(DrawPolylineStruct));
  796.         ((DrawPolylineStruct *) NewDrawStruct) -> Points = (int *)
  797.         MyMalloc(sizeof(int) * 2 *
  798.              ((DrawPolylineStruct *) DrawStruct) -> NumOfPoints);
  799.         GEN_COPY(((DrawPolylineStruct *) NewDrawStruct) -> Points,
  800.              ((DrawPolylineStruct *) DrawStruct) -> Points,
  801.              sizeof(int) * 2 *
  802.              ((DrawPolylineStruct *) DrawStruct) -> NumOfPoints);
  803.         break;
  804.     case DRAW_CONNECTION_STRUCT_TYPE:
  805.         NewDrawStruct = (DrawGenericStruct *)
  806.                        MyMalloc(sizeof(DrawConnectionStruct));
  807.         GEN_COPY(NewDrawStruct, DrawStruct, sizeof(DrawConnectionStruct));
  808.         break;
  809.     case DRAW_TEXT_STRUCT_TYPE:
  810.         NewDrawStruct = (DrawGenericStruct *) MyMalloc(sizeof(DrawTextStruct));
  811.         GEN_COPY(NewDrawStruct, DrawStruct, sizeof(DrawTextStruct));
  812.         ((DrawTextStruct *) NewDrawStruct) -> Text =
  813.         strdup(((DrawTextStruct *) DrawStruct) -> Text);
  814.         break;
  815.     case DRAW_LIB_ITEM_STRUCT_TYPE:
  816.         NewDrawStruct = (DrawGenericStruct *)
  817.                       MyMalloc(sizeof(DrawLibItemStruct));
  818.         GEN_COPY(NewDrawStruct, DrawStruct, sizeof(DrawLibItemStruct));
  819.         if (((DrawLibItemStruct *) DrawStruct) -> ChipName)
  820.         (((DrawLibItemStruct *) NewDrawStruct) -> ChipName) =
  821.             strdup(((DrawLibItemStruct *) DrawStruct) -> ChipName);
  822.         if (((DrawLibItemStruct *) DrawStruct) -> PartName)
  823.         (((DrawLibItemStruct *) NewDrawStruct) -> PartName) =
  824.             strdup(((DrawLibItemStruct *) DrawStruct) -> PartName);
  825.         break;
  826.     case DRAW_PICK_ITEM_STRUCT_TYPE:
  827.         PickedList = (DrawPickedStruct *) DrawStruct;
  828.         while (PickedList) {
  829.         NewPickedItem = (DrawPickedStruct *)
  830.                        MyMalloc(sizeof(DrawPickedStruct));
  831.         NewPickedItem -> StructType = DRAW_PICK_ITEM_STRUCT_TYPE;
  832.         NewPickedItem -> Pnext = NULL;
  833.         if (NewDrawStruct == NULL)
  834.             NewDrawStruct = (DrawGenericStruct *) NewPickedItem;
  835.         if (LastPickedItem != NULL)
  836.             LastPickedItem -> Pnext = NewPickedItem;
  837.         LastPickedItem = NewPickedItem;
  838.  
  839.         NewPickedItem -> PickedStruct =
  840.             CopyStructLocal(PickedList -> PickedStruct);
  841.  
  842.         PickedList = PickedList -> Pnext;
  843.         }
  844.         break;
  845.     }
  846.  
  847.     return NewDrawStruct;
  848. }
  849.  
  850. /*****************************************************************************
  851. * Routine to delete a given struct.                         *
  852. *****************************************************************************/
  853. void FreeStruct(DrawGenericStruct *DrawStruct)
  854. {
  855.     DrawPickedStruct *PickedList, *PickedItem;
  856.  
  857.     switch (DrawStruct -> StructType) {
  858.     case DRAW_POLYLINE_STRUCT_TYPE:
  859.         MyFree((VoidPtr) ((DrawPolylineStruct *) DrawStruct) -> Points);
  860.         MyFree((VoidPtr) DrawStruct);
  861.         break;
  862.     case DRAW_CONNECTION_STRUCT_TYPE:
  863.         MyFree((VoidPtr) DrawStruct);
  864.         break;
  865.     case DRAW_TEXT_STRUCT_TYPE:
  866.         MyFree((VoidPtr) ((DrawTextStruct *) DrawStruct) -> Text);
  867.         MyFree((VoidPtr) DrawStruct);
  868.         break;
  869.     case DRAW_LIB_ITEM_STRUCT_TYPE:
  870.         if (((DrawLibItemStruct *) DrawStruct) -> ChipName)
  871.         MyFree((VoidPtr) ((DrawLibItemStruct *) DrawStruct) -> ChipName);
  872.         if (((DrawLibItemStruct *) DrawStruct) -> PartName)
  873.         MyFree((VoidPtr) ((DrawLibItemStruct *) DrawStruct) -> PartName);
  874.         MyFree((VoidPtr) DrawStruct);
  875.         break;
  876.     case DRAW_PICK_ITEM_STRUCT_TYPE:
  877.         PickedList = (DrawPickedStruct *) DrawStruct;
  878.         while (PickedList) {
  879.         PickedItem = PickedList;
  880.         PickedList = PickedList -> Pnext;
  881.         FreeStruct(PickedItem -> PickedStruct);
  882.         MyFree((VoidPtr) PickedItem);
  883.         }
  884.         break;
  885.     }
  886. }
  887.  
  888. /*****************************************************************************
  889. * Routine to pick a object from global drawing object list.             *
  890. *****************************************************************************/
  891. DrawGenericStruct *PickStruct(char *Header, BooleanType OnlyLibItem)
  892. {
  893.     BooleanType Snapped, Draw = TRUE;
  894.     int i, x, y, OrigX, OrigY, OrigXScrn, OrigYScrn, Event;
  895.     DrawPickedStruct *DontPickList = NULL, *PickedList = NULL, *PickedItem;
  896.     DrawGenericStruct *DrawStruct;
  897.  
  898.     IntrPushCursorType();
  899.     Cursor.CursorType = INTR_CURSOR_CROSS;
  900.     IntrSetCursorType(&Cursor);
  901.  
  902.     IntrDrawMessage(Header, EEPopUpForeColor, EEPopUpBackColor);
  903.  
  904.     if (IntrGetEventWaitSA(&OrigXScrn, &OrigYScrn) == INTR_EVNT_ABORT) {
  905.     IntrPopCursorType();
  906.     IntrEraseMessage();
  907.  
  908.     return NULL;
  909.     }
  910.     OrigX = OrigXScrn;
  911.     OrigY = OrigYScrn;
  912.     OrigX = EE_SNAP(GRInvMapX(OrigX));
  913.     OrigY = EE_SNAP(GRInvMapY(OrigY));
  914.  
  915.     do {
  916.     x = OrigX;
  917.     y = OrigY;
  918.     if ((Snapped = SnapPoint2(&x, &y, OnlyLibItem,
  919.             EEActiveWindow -> EEDrawList, DontPickList)) == FALSE) break;
  920.  
  921.     /* Lets see if the user likes this picked structure: */
  922.     do {
  923.         Draw = !Draw;
  924.         RedrawOneStruct(LastSnappedStruct, GR_COPY_PUT,
  925.                 Draw ? EE_DRAW_COLOR : EE_ERASE_COLOR);
  926.         delay(300);
  927.         Event = IntrGetTextEventNoWait();
  928.     }
  929.     while (Event != INTR_EVNT_ABORT && Event != INTR_EVNT_SELECT);
  930.     if (!Draw) RedrawOneStruct(LastSnappedStruct, GR_COPY_PUT, EE_DRAW_COLOR);
  931.  
  932.     if (Event == INTR_EVNT_ABORT) {
  933.         /* Put this structure in the dont pick list, and try again: */
  934.         PickedItem = (DrawPickedStruct *) MyMalloc(sizeof(DrawPickedStruct));
  935.         PickedItem -> StructType = DRAW_PICK_ITEM_STRUCT_TYPE;
  936.         PickedItem -> PickedStruct = LastSnappedStruct;
  937.         PickedItem -> Pnext = DontPickList;
  938.         DontPickList = PickedItem;
  939.     }
  940.     } while (Event != INTR_EVNT_SELECT);
  941.  
  942.     if (DontPickList == NULL && !Snapped) {
  943.     /*   Wait for the second points to define a box everything inside is */
  944.     /* to considered picked.                         */
  945.         Cursor.CursorType = INTR_CURSOR_BOX_LAST;
  946.         Cursor.LastX = OrigXScrn;
  947.         Cursor.LastY = OrigYScrn;
  948.     IntrSetCursorType(&Cursor);
  949.     if (IntrGetEventWaitSA(&x, &y) == INTR_EVNT_ABORT) {
  950.         IntrPopCursorType();
  951.         IntrEraseMessage();
  952.  
  953.         return NULL;
  954.     }
  955.     x = EE_SNAP(GRInvMapX(x));
  956.     y = EE_SNAP(GRInvMapY(y));
  957.     if (x < OrigX) {
  958.         i = x;
  959.         x = OrigX;
  960.         OrigX = i;
  961.     }
  962.     if (y < OrigY) {
  963.         i = y;
  964.         y = OrigY;
  965.         OrigY = i;
  966.     }
  967.  
  968.     for (DrawStruct = EEActiveWindow -> EEDrawList;
  969.          DrawStruct != NULL;
  970.          DrawStruct = DrawStruct -> Pnext) {
  971.         if (DrawStructInBox(OrigX, OrigY, x, y, DrawStruct)) {
  972.         /* Put this structure in the picked list: */
  973.         PickedItem = (DrawPickedStruct *)
  974.             MyMalloc(sizeof(DrawPickedStruct));
  975.         PickedItem -> StructType = DRAW_PICK_ITEM_STRUCT_TYPE;
  976.         PickedItem -> PickedStruct = DrawStruct;
  977.         PickedItem -> Pnext = PickedList;
  978.         PickedList = PickedItem;
  979.         }
  980.     }
  981.  
  982.     IntrEraseMessage();
  983.     IntrPopCursorType();
  984.  
  985.     if (PickedList && PickedList -> Pnext == NULL) {
  986.         /* Only one item was picked - convert to scalar form (no list): */
  987.         PickedItem = PickedList;
  988.         PickedList = (DrawPickedStruct *) PickedList -> PickedStruct;
  989.         MyFree((VoidPtr) PickedItem);
  990.     }
  991.  
  992.     if (PickedList != NULL) {
  993.         PickedBoxMinX = OrigX;
  994.         PickedBoxMinY = OrigY;
  995.         PickedBoxMaxX = x;
  996.         PickedBoxMaxY = y;
  997.     }
  998.  
  999.     return (DrawGenericStruct *) PickedList;
  1000.     }
  1001.     else {
  1002.     while (DontPickList) {
  1003.         PickedItem = DontPickList;
  1004.         DontPickList = DontPickList -> Pnext;
  1005.         MyFree((VoidPtr) PickedItem);
  1006.     }
  1007.  
  1008.     IntrEraseMessage();
  1009.     IntrPopCursorType();
  1010.  
  1011.     return Snapped ? LastSnappedStruct : NULL;
  1012.     }
  1013. }
  1014.  
  1015. /*****************************************************************************
  1016. * Interface routine to snap a point relative to all structures defined.      *
  1017. *****************************************************************************/
  1018. BooleanType SnapPoint(int *OrigX, int *OrigY, BooleanType OnlyLibItem)
  1019. {
  1020.     return SnapPoint2(OrigX, OrigY, OnlyLibItem,
  1021.                          EEActiveWindow -> EEDrawList, NULL);
  1022. }
  1023.  
  1024. /*****************************************************************************
  1025. * Routine to search all objects for the closest point to a given point, in   *
  1026. * drawing space, and snap it to that points if closer than SnapDistance.     *
  1027. * Note we use L1 norm as distance measure, as it is the fastest.         *
  1028. * This routine updates LastSnappedStruct to the last object used in to snap  *
  1029. * a point. This variable is global to this module only (see above).         *
  1030. * If DontSnapList is not NULL, structes in this list are skipped.         *
  1031. * The routine returns TRUE if point was snapped.                 *
  1032. * The points is also snapped to the EE_SNAP.                     *
  1033. *****************************************************************************/
  1034. BooleanType SnapPoint2(int *OrigX, int *OrigY, BooleanType OnlyLibItem,
  1035.            DrawGenericStruct *DrawList, DrawPickedStruct *DontSnapList)
  1036. {
  1037.     int i, *Points, x = *OrigX, y = *OrigY, x1, y1, x2, y2, NumOfPoints2,
  1038.     ClosestX = 16383, ClosestY = 16383;
  1039.     unsigned int Dist, CrntDist = 16383;
  1040.     DrawPickedStruct *DontSnap;
  1041.  
  1042.     for (; DrawList != NULL; DrawList = DrawList -> Pnext) {
  1043.     /* Make sure this structure is NOT in the dont snap list: */
  1044.     for (DontSnap = DontSnapList;
  1045.          DontSnap != NULL;
  1046.          DontSnap = DontSnap -> Pnext)
  1047.         if (DontSnap -> PickedStruct == DrawList) break;
  1048.     if (DontSnap -> PickedStruct == DrawList) continue;
  1049.  
  1050.     switch (DrawList -> StructType) {
  1051.         case DRAW_POLYLINE_STRUCT_TYPE:
  1052.         if (OnlyLibItem) break;
  1053.         Points = ((DrawPolylineStruct *) DrawList) -> Points;
  1054.         NumOfPoints2 =
  1055.             ((DrawPolylineStruct *) DrawList) -> NumOfPoints * 2;
  1056.         for (i = 0; i < NumOfPoints2; i += 2) {
  1057.             Dist = ((unsigned int) ABS(Points[i] - x)) +
  1058.                ((unsigned int) ABS(Points[i+1] - y));
  1059.             if (CrntDist > Dist) {
  1060.             CrntDist = Dist;
  1061.             LastSnappedStruct = DrawList;
  1062.             ClosestX = Points[i];
  1063.             ClosestY = Points[i+1];
  1064.             }
  1065.             if (i < NumOfPoints2 - 2) {
  1066.             /* Maybe we should snap the point to the middle of   */
  1067.             /* the line instead.                     */
  1068.             if ((Points[i] > x && Points[i+2] < x) ||
  1069.                 (Points[i] < x && Points[i+2] > x)) {
  1070.                 /* X value in middle of current line segment: */
  1071.                 Dist = (unsigned int) ABS(Points[i+1] - y);
  1072.                 if (CrntDist > Dist) {
  1073.                 CrntDist = Dist;
  1074.                 LastSnappedStruct = DrawList;
  1075.                 ClosestX = x;
  1076.                 ClosestY = Points[i+1];
  1077.                 }
  1078.             }
  1079.             if ((Points[i+1] > y) && (Points[i+3] < y) ||
  1080.                 (Points[i+1] < y) && (Points[i+3] > y)) {
  1081.                 /* Y value in middle of current line segment: */
  1082.                 Dist = (unsigned int) ABS(Points[i] - x);
  1083.                 if (CrntDist > Dist) {
  1084.                 CrntDist = Dist;
  1085.                 LastSnappedStruct = DrawList;
  1086.                 ClosestX = Points[i];
  1087.                 ClosestY = y;
  1088.                 }
  1089.             }
  1090.             }
  1091.         }
  1092.         break;
  1093.         case DRAW_CONNECTION_STRUCT_TYPE:
  1094.         if (OnlyLibItem) break;
  1095.         Dist = ((unsigned int)
  1096.             ABS(((DrawConnectionStruct *) DrawList) -> PosX - x)) +
  1097.                ((unsigned int)
  1098.             ABS(((DrawConnectionStruct *) DrawList) -> PosY - y));
  1099.         if (CrntDist > Dist) {
  1100.             CrntDist = Dist;
  1101.             LastSnappedStruct = DrawList;
  1102.             ClosestX = ((DrawConnectionStruct *) DrawList) -> PosX;
  1103.             ClosestY = ((DrawConnectionStruct *) DrawList) -> PosY;
  1104.         }
  1105.         break;
  1106.         case DRAW_TEXT_STRUCT_TYPE:
  1107.         if (OnlyLibItem) break;
  1108.         if (((DrawTextStruct *) DrawList) -> Orient ==
  1109.                             TEXT_ORIENT_HORIZ) {
  1110.             x1 = GRMapX(((DrawTextStruct *) DrawList) -> PosX) -
  1111.             GRGetTextWidth(((DrawTextStruct *) DrawList) -> Text) / 2;
  1112.             x2 = GRMapX(((DrawTextStruct *) DrawList) -> PosX) +
  1113.             GRGetTextWidth(((DrawTextStruct *) DrawList) -> Text) / 2;
  1114.             y1 = GRMapY(((DrawTextStruct *) DrawList) -> PosY) -
  1115.             GRGetTextHeight(((DrawTextStruct *) DrawList) -> Text) / 2;
  1116.             y2 = GRMapY(((DrawTextStruct *) DrawList) -> PosY) +
  1117.             GRGetTextHeight(((DrawTextStruct *) DrawList) -> Text) / 2;
  1118.         }
  1119.         else {
  1120.             x1 = GRMapX(((DrawTextStruct *) DrawList) -> PosX) -
  1121.             GRGetTextHeight(((DrawTextStruct *) DrawList) -> Text) / 2;
  1122.             x2 = GRMapX(((DrawTextStruct *) DrawList) -> PosX) +
  1123.             GRGetTextHeight(((DrawTextStruct *) DrawList) -> Text) / 2;
  1124.             y1 = GRMapY(((DrawTextStruct *) DrawList) -> PosY) -
  1125.             GRGetTextWidth(((DrawTextStruct *) DrawList) -> Text) / 2;
  1126.             y2 = GRMapY(((DrawTextStruct *) DrawList) -> PosY) +
  1127.             GRGetTextWidth(((DrawTextStruct *) DrawList) -> Text) / 2;
  1128.         }
  1129.         x1 = GRInvMapX(x1);
  1130.         x2 = GRInvMapX(x2);
  1131.         y1 = GRInvMapY(y1);
  1132.         y2 = GRInvMapY(y2);
  1133.         if (x >= x1 && x <= x2) {
  1134.             if (y >= y1 && y <= y2)
  1135.             Dist = 0;
  1136.             else
  1137.             Dist = MIN(ABS(y - y1), ABS(y - y2));
  1138.         }
  1139.         else if (y >= y1 && y <= y2) {
  1140.             if (x >= x1 && x <= x2)
  1141.             Dist = 0;
  1142.             else
  1143.             Dist = MIN(ABS(x - x1), ABS(x - x2));
  1144.         }
  1145.         else
  1146.             Dist = 16363;
  1147.         if (CrntDist > Dist) {
  1148.             CrntDist = Dist;
  1149.             LastSnappedStruct = DrawList;
  1150.             ClosestX = x + Dist;
  1151.             ClosestY = y;
  1152.         }
  1153.         break;
  1154.         case DRAW_LIB_ITEM_STRUCT_TYPE:
  1155.         /* Check this library item iff our point is in its bbox: */
  1156.         if (((DrawLibItemStruct *) DrawList) -> BBoxMinX -
  1157.                             EESnapDistance <= x &&
  1158.             ((DrawLibItemStruct *) DrawList) -> BBoxMaxX +
  1159.                             EESnapDistance >= x &&
  1160.             ((DrawLibItemStruct *) DrawList) -> BBoxMinY -
  1161.                             EESnapDistance <= y &&
  1162.             ((DrawLibItemStruct *) DrawList) -> BBoxMaxY +
  1163.                             EESnapDistance >= y)
  1164.             SnapLibItemPoint(x, y, &ClosestX, &ClosestY,
  1165.                      (DrawLibItemStruct *) DrawList);
  1166.         Dist = ((unsigned int) ABS(ClosestX - x)) +
  1167.                ((unsigned int) ABS(ClosestY - y));
  1168.         if (CrntDist > Dist) {
  1169.             CrntDist = Dist;
  1170.             LastSnappedStruct = DrawList;
  1171.         }
  1172.         break;
  1173.     }
  1174.     }
  1175.  
  1176.     /* Lets find the euclidian L2 distance: */
  1177.     if (SQR(((double) ClosestX) - x) + SQR(((double) ClosestY) - y) <
  1178.     SQR(EESnapDistance)) {
  1179.     /* We snap the point, make sure it is on EE_SNAP boundary: */
  1180.     ClosestX = EE_SNAP(ClosestX);
  1181.     ClosestY = EE_SNAP(ClosestY);
  1182.     *OrigX = ClosestX;
  1183.     *OrigY = ClosestY;
  1184.  
  1185.     return TRUE;
  1186.     }
  1187.     else
  1188.     return FALSE;
  1189. }
  1190.  
  1191. /*****************************************************************************
  1192. * Routine to test if an object has non empty intersection with the box       *
  1193. * defined by x1/y1 and x2/y2 (x1 < x2, y1 < y2), and return TRUE if so. This *
  1194. * routine is used to pick all points in a given box.                 *
  1195. *****************************************************************************/
  1196. BooleanType DrawStructInBox(int x1, int y1, int x2, int y2,
  1197.                         DrawGenericStruct *DrawStruct)
  1198. {
  1199.     int i, *Points, xt1, yt1, xt2, yt2, NumOfPoints2;
  1200.  
  1201.     switch (DrawStruct -> StructType) {
  1202.         case DRAW_POLYLINE_STRUCT_TYPE:
  1203.         Points = ((DrawPolylineStruct *) DrawStruct) -> Points;
  1204.         NumOfPoints2 =
  1205.             ((DrawPolylineStruct *) DrawStruct) -> NumOfPoints * 2;
  1206.         for (i = 0; i < NumOfPoints2; i += 2) {
  1207.             if (Points[i] >= x1 && Points[i] <= x2 &&
  1208.             Points[i+1] >= y1 && Points[i+1] <=y2) return TRUE;
  1209.         }
  1210.         break;
  1211.         case DRAW_CONNECTION_STRUCT_TYPE:
  1212.         if (((DrawConnectionStruct *) DrawStruct) -> PosX >= x1 &&
  1213.             ((DrawConnectionStruct *) DrawStruct) -> PosX <= x2 &&
  1214.             ((DrawConnectionStruct *) DrawStruct) -> PosY >= y1 &&
  1215.             ((DrawConnectionStruct *) DrawStruct) -> PosY <= y2)
  1216.             return TRUE;
  1217.         break;
  1218.         case DRAW_TEXT_STRUCT_TYPE:
  1219.         if (((DrawTextStruct *) DrawStruct) -> Orient ==
  1220.                             TEXT_ORIENT_HORIZ) {
  1221.             xt1 = GRMapX(((DrawTextStruct *) DrawStruct) -> PosX) -
  1222.             GRGetTextWidth(((DrawTextStruct *) DrawStruct) ->
  1223.                                   Text) / 2;
  1224.             xt2 = GRMapX(((DrawTextStruct *) DrawStruct) -> PosX) +
  1225.             GRGetTextWidth(((DrawTextStruct *) DrawStruct) ->
  1226.                                   Text) / 2;
  1227.             yt1 = GRMapY(((DrawTextStruct *) DrawStruct) -> PosY) -
  1228.             GRGetTextHeight(((DrawTextStruct *) DrawStruct) ->
  1229.                                   Text) / 2;
  1230.             yt2 = GRMapY(((DrawTextStruct *) DrawStruct) -> PosY) +
  1231.             GRGetTextHeight(((DrawTextStruct *) DrawStruct) ->
  1232.                                   Text) / 2;
  1233.         }
  1234.         else {
  1235.             xt1 = GRMapX(((DrawTextStruct *) DrawStruct) -> PosX) -
  1236.             GRGetTextHeight(((DrawTextStruct *) DrawStruct) ->
  1237.                                   Text) / 2;
  1238.             xt2 = GRMapX(((DrawTextStruct *) DrawStruct) -> PosX) +
  1239.             GRGetTextHeight(((DrawTextStruct *) DrawStruct) ->
  1240.                                   Text) / 2;
  1241.             yt1 = GRMapY(((DrawTextStruct *) DrawStruct) -> PosY) -
  1242.             GRGetTextWidth(((DrawTextStruct *) DrawStruct) ->
  1243.                                   Text) / 2;
  1244.             yt2 = GRMapY(((DrawTextStruct *) DrawStruct) -> PosY) +
  1245.             GRGetTextWidth(((DrawTextStruct *) DrawStruct) ->
  1246.                                   Text) / 2;
  1247.         }
  1248.         xt1 = GRInvMapX(xt1);
  1249.         xt2 = GRInvMapX(xt2);
  1250.         yt1 = GRInvMapY(yt1);
  1251.         yt2 = GRInvMapY(yt2);
  1252.         if ((xt1 >= x1 && xt1 <= x2 && yt1 >= y1 && yt1 <= y2) ||
  1253.             (xt2 >= x1 && xt2 <= x2 && yt2 >= y1 && yt2 <= y2))
  1254.             return TRUE;
  1255.         break;
  1256.         case DRAW_LIB_ITEM_STRUCT_TYPE:
  1257.         /* Check this library item iff our point is in its bbox: */
  1258.         xt1 = ((DrawLibItemStruct *) DrawStruct) -> BBoxMinX;
  1259.         xt2 = ((DrawLibItemStruct *) DrawStruct) -> BBoxMaxX;
  1260.         yt1 = ((DrawLibItemStruct *) DrawStruct) -> BBoxMinY;
  1261.         yt2 = ((DrawLibItemStruct *) DrawStruct) -> BBoxMaxY;
  1262.  
  1263.         /* See if we can trivially reject using the bounding boxes,  */
  1264.         /* otherwise use the full power of the library to decide.    */
  1265.         if (!(xt1 > x2 || yt1 > y2 || xt2 < x1 || yt2 < y1) &&
  1266.             LibItemInBox(x1, y1, x2, y2,
  1267.             (DrawLibItemStruct *) DrawStruct))
  1268.             return TRUE;
  1269.         break;
  1270.     }
  1271.  
  1272.     return FALSE;
  1273. }
  1274.